/*
 * Copyright (c) 2025 Li Auto Inc. and its affiliates
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef LIXDPSOCKETUDP_HPP
#define LIXDPSOCKETUDP_HPP

#include <lixdpsocket.hpp>
#include <deps/common/IPLocator.h>
#include <deps/common/Locator.h>

using LixdpSocket = lixdp::LixdpSocket;

namespace vbs {
namespace transport {

enum SocketType {
    SOCKET_TYPE_UDP,
    SOCKET_TYPE_XDP,
};

class UDPChannelResource;
class UDPSenderResource;
class LixdpSocketUDP : public LixdpSocket {
 public:
    LixdpSocketUDP(std::string& ip, uint16_t port, uint32_t xdp_rx_queue_num = 1);
    ~LixdpSocketUDP() {}

    virtual int lixdp_receive(const uint8_t* data, size_t size, struct sockaddr* remote_addr) override;
    void set_channel_resource(UDPChannelResource* channel_resource) { channel_resource_ = channel_resource; }

    UDPChannelResource* get_channel_resource() const { return channel_resource_; }

    void set_sender_resource(UDPSenderResource* sender_resource) { sender_resource_ = sender_resource; }

    UDPSenderResource* get_sender_resource() const { return sender_resource_; }

    vbsutil::xmlparser::Locator_t get_input_locator() { return input_locator_; }

    static bool sockaddr_to_locator(const struct sockaddr* remote_addr, vbsutil::xmlparser::Locator_t& locator);

    static bool locator_to_sockaddr(const vbsutil::xmlparser::Locator_t& locator, struct sockaddr* remote_addr);

    vbsutil::xmlparser::Locator_t get_locator() const { return input_locator_; }

    std::string get_locator_string() const { return vbsutil::xmlparser::IPLocator::to_string(input_locator_); }

    std::string get_ip_string() const { return vbsutil::xmlparser::IPLocator::ip_to_string(input_locator_); }

    bool is_multicast() const { return vbsutil::xmlparser::IPLocator::isMulticast(input_locator_); }

    bool is_local() const { return vbsutil::xmlparser::IPLocator::isLocal(input_locator_); }

    uint16_t get_local_port() const { return vbsutil::xmlparser::IPLocator::getPhysicalPort(input_locator_); }

    void set_local_port(const uint16_t port) { vbsutil::xmlparser::IPLocator::setPhysicalPort(input_locator_, port); }

    static int load_kern_prog(std::vector<std::string>& dev_names);

 private:
    UDPChannelResource* channel_resource_;
    UDPSenderResource* sender_resource_;
    vbsutil::xmlparser::Locator_t input_locator_;
};

}  // namespace transport
}  // namespace vbs

#endif  // LIXDPSOCKETUDP_HPP
